package com.gzl.exercise;

import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.StringJoiner;

/**
 * @PROJECT_NAME: exercise
 * @NAME: 错误的集合
 * @DESCRIPTION: 简单
 * @USER: gaozengliang
 * @DATE: 2023/4/28
 */
public class 错误的集合 {

    /*
        集合 s 包含从 1 到 n 的整数。不幸的是，因为数据错误，导致集合里面某一个数字复制了成了集合里面的另外一个数字的值，导致集合 丢失了一个数字 并且 有一个数字重复 。
        给定一个数组 nums 代表了集合 S 发生错误后的结果。
        请你找出重复出现的整数，再找到丢失的整数，将它们以数组的形式返回。

        示例 1：
        输入：nums = [1,2,2,4]
        输出：[2,3]

        示例 2：
        输入：nums = [1,1]
        输出：[1,2]

        提示：
        2 <= nums.length <= 10^4
        1 <= nums[i] <= 10^4
    * */

    /*
        思路：利用求和公式 (n * (n + 1)) / 2求出原来数组的和，在计算出现在数组的和，比如相减差为 a，就是相差 a个位置的重复了，然后遍历找出这个位置
        比如示例1，两个和相差 1 ，就是相差 1 个位置的数字重复了
        比如 1,2,3,4,2,6 ，原来和为 21，现在和为 18，也就是相差 3 个位置的数字丢失了，重复位置原来的值与现在的值的差值即为 3
    */
    @Test
    void findErrorNums() {
        int[] nums = {8,7,3,5,3,6,1,4};
//        int[] nums = {1,5,3,4,5,6};
//        int[] nums = {1,2,3,4,2,6};
//        int[] nums = {1,2,2,4};
//        int[] nums = {2,2};
//        int[] nums = {1,1};
//        int[] nums = {3,2,2};
//        int[] nums = {3,2,2};
        int n = nums.length;

        int iSum = (n * (n + 1)) / 2; // 计算原来应该有的和
        int nSum = Arrays.stream(nums).sum(); // 计算现在的和
        int diff = iSum-nSum; // 计算差值
        // 排序
        Arrays.sort(nums);
        int i = 0;
        // 找出重复的数值
        while (i<n-1){
            if (nums[i] == nums[i+1]){
                break;
            }
            i++;
        }

        int[] ans = new int[2];
        ans[0] = nums[i];
        ans[1] = diff + nums[i];

        // 将要连接的字符串之间以逗号进行分隔。
        StringJoiner joiner = new StringJoiner(",");
        //通过 Arrays.stream(ans) 将整数数组 ans 转换为一个流（Stream）对象
        //使用 lambda 表达式 num -> joiner.add(String.valueOf(num))，对于每个元素 num，将其转换为字符串类型后，通过 joiner.add 方法将其添加到 joiner 对象中
        Arrays.stream(ans).forEach(num -> joiner.add(String.valueOf(num)));

        System.out.print(joiner.toString());
    }

}
